package com.zhaopin.qa.jmeter.plugins.multienvuser.controller;

import java.awt.BorderLayout;
import java.awt.Container;
import java.awt.GridLayout;

import java.awt.event.ItemEvent;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JTabbedPane;

import org.apache.jmeter.config.Arguments;
import org.apache.jmeter.control.gui.LoopControlPanel;
import org.apache.jmeter.gui.util.HorizontalPanel;
import org.apache.jmeter.gui.util.VerticalPanel;
import org.apache.jmeter.testelement.TestElement;
import org.apache.jmeter.testelement.property.JMeterProperty;
import org.apache.jmeter.testelement.property.PropertyIterator;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.apache.commons.lang3.StringUtils;

import com.zhaopin.qa.jmeter.plugins.multienvuser.config.EnvArgument.ArgumentsType;

public class MultiEnvUserControllerPanel extends LoopControlPanel {

	private static final long serialVersionUID = -394914559839491874L;

	private static final Logger log = LoggerFactory.getLogger(MultiEnvUserControllerPanel.class);

	/**
	 * 环境选择使用单选框
	 */
	private transient JComboBox<String> envSelect;

	/**
	 * 用户选择使用复选框
	 */
	private transient List<JCheckBox> userSelectBoxList = new ArrayList<>();

	/**
	 * 环境面板
	 */
	private transient JTabbedPane envSetPane;

	/**
	 * 环境参数面板
	 */
	private Map<String, MultiEnvArgumentsPanel> envSetPaneMap = new HashMap<String, MultiEnvArgumentsPanel>();

	/**
	 * 环境面板中用于添加用户的tab
	 */
	private Map<String, JTabbedPane> userSetTabPaneMap = new HashMap<String, JTabbedPane>();

	/**
	 * 用户面板
	 */
	private Map<String, Map<String, MultiEnvUserArgumentsPanel>> userSetEnvArgumentsPanelMap = new HashMap<String, Map<String, MultiEnvUserArgumentsPanel>>();

	private JPanel instance = this;

	private final boolean standalone;

	public MultiEnvUserControllerPanel() {
		this(true);
	}

	public MultiEnvUserControllerPanel(boolean standalone) {
		this.standalone = standalone;
		initGui();
	}

	@Override
	public String getStaticLabel() {
		return "Multi-EnvUser Controller";
	}

	@Override
	public String getLabelResource() {
		return "多环境多用户控制器";
	}

	/**
	 * 设置环境选择面板
	 * 
	 * @return
	 */
	private JPanel createEnvSelectPanel() {
		JPanel envSelectPanel = new HorizontalPanel();
		envSelectPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "选择环境和用户")); // $NON-NLS-1$
		envSelectPanel.add(new JLabel("选择执行环境："));

		envSelect = new JComboBox<>();
		envSelect.addItemListener((e) -> {
			switch (e.getStateChange()) {
			case ItemEvent.SELECTED:
				String env = (String) envSelect.getSelectedItem();

				/*
				 * 配置右侧显示选中环境的用户
				 */
				configUserSelectPanel(env);

				/*
				 * 配置tab显示选中的环境
				 */
				envSetPane.setSelectedIndex(envSetPane.indexOfTab(env));
				break;
			default:
				break;
			}

		});

		envSelectPanel.add(envSelect);

		JButton addEnvBtn = new JButton("添加环境");

		addEnvBtn.addActionListener((e) -> {

			String newEnvName = JOptionPane.showInputDialog(instance, "请输入", "要添加的环境名称",
					JOptionPane.INFORMATION_MESSAGE);

			if (StringUtils.isNotEmpty(newEnvName) || envSetPaneMap.containsKey(newEnvName)) {
				addNewEnv(newEnvName);
			} else {
				JOptionPane.showMessageDialog(instance, "添加环境失败", "未添加环境！!", JOptionPane.WARNING_MESSAGE);
			}
		});

		envSelectPanel.add(addEnvBtn);

		JButton removeEnvBtn = new JButton("移除环境");

		removeEnvBtn.addActionListener((e) -> {
			removeEnv((String) envSelect.getSelectedItem());
		});
		envSelectPanel.add(removeEnvBtn);

		envSelectPanel.add(new JLabel("选择用户："));

		envSelectPanel.add(createUserSelectPanel());

		JButton addUserBtn = new JButton("添加用户");

		addUserBtn.addActionListener((e) -> {
			String newUserName = JOptionPane.showInputDialog(envSelectPanel, null, "请输入要添加的用户名称",
					JOptionPane.PLAIN_MESSAGE);
			if (StringUtils.isNotEmpty((String) envSelect.getSelectedItem()) && StringUtils.isNotEmpty(newUserName)) {
				addNewUser((String) envSelect.getSelectedItem(), newUserName);
			}
		});

		envSelectPanel.add(addUserBtn);

		JButton removeUserBtn = new JButton("移除用户");

		removeUserBtn.addActionListener((e) -> {
			for (JCheckBox jCheckBox : userSelectBoxList) {
				if (jCheckBox.isVisible() && jCheckBox.isSelected()) {
					removeUser((String) envSelect.getSelectedItem(), jCheckBox.getText());
				}
			}
		});

		envSelectPanel.add(removeUserBtn);

		return envSelectPanel;
	}

	/**
	 * 移除该环境 同时环境的用户也会被移除
	 * 
	 * @param env
	 */
	private void removeEnv(String env) {

		int showConfirmDialog = JOptionPane.showConfirmDialog(instance, "确定要移除" + env + "环境吗？", "移除确认",
				JOptionPane.YES_NO_OPTION);
		if (JOptionPane.YES_OPTION == showConfirmDialog) {

			// 移除的只是参数面板 需要移除的是整个jpanel
			Container panel = envSetPaneMap.remove(env).getParent();
			envSetPane.remove(panel);

			userSetTabPaneMap.remove(env);
			userSetEnvArgumentsPanelMap.remove(env);

			for (int i = 0; i < envSelect.getItemCount(); i++) {
				String item = envSelect.getItemAt(i);
				if (env.equals(item)) {
					envSelect.removeItemAt(i);
					break;
				}
			}

		}
	}

	/**
	 * 移除该环境
	 * 
	 * @param selectedItem
	 */
	private void removeUser(String env, String userName) {
		int showConfirmDialog = JOptionPane.showConfirmDialog(instance, "确定要移除" + env + "环境的" + userName + "用户吗？",
				"移除确认", JOptionPane.YES_NO_OPTION);
		if (JOptionPane.YES_OPTION == showConfirmDialog) {
			userSelectBoxList.stream().filter(box -> box.getText().equals(userName)).forEach(box -> {
				box.setSelected(false);
				box.setVisible(false);
				box.setText("un-used");
			});

			userSetTabPaneMap.get(env).remove(userSetEnvArgumentsPanelMap.get(env).remove(userName));
		}
	}

	/**
	 * 点击添加新环境的时候用
	 * 
	 * @param env
	 */
	private void addNewEnv(String env) {
		if (!envSetPaneMap.containsKey(env)) {
			// log.info(this.getComment() + "-->添加新环境：" + env);
			createEnvUserSetPanel(env);
			envSelect.addItem(env);
		}
	}

	private void addNewUser(String env, String userName) {
		if (userSetEnvArgumentsPanelMap.containsKey(env)
				&& userSetEnvArgumentsPanelMap.get(env).containsKey(userName)) {
			return;
		}

		MultiEnvUserArgumentsPanel argumentsPanel = new MultiEnvUserArgumentsPanel(env + "." + userName);

		userSetEnvArgumentsPanelMap.get(env).put(userName, argumentsPanel);

		userSetTabPaneMap.get(env).addTab(userName, argumentsPanel);

		configUserSelectPanel(env);
	}

	private JPanel createUserSelectPanel() {

		JPanel userSelectPanel = new HorizontalPanel();

		for (int i = 0; i < 10; i++) {
			JCheckBox box = new JCheckBox("un-used");
			box.setVisible(false);
			box.setSelected(false);
			userSelectBoxList.add(box);
			userSelectPanel.add(box);
		}

		return userSelectPanel;
	}

	private void configUserSelectPanel(String env) {

		for (JCheckBox jCheckBox : userSelectBoxList) {
			jCheckBox.setVisible(false);
			jCheckBox.setSelected(false);
		}

		Map<String, MultiEnvUserArgumentsPanel> map = userSetEnvArgumentsPanelMap.get(env);

		int i = 0;
		Iterator<String> iterator = map.keySet().iterator();

		while (iterator.hasNext()) {
			JCheckBox jCheckBox = userSelectBoxList.get(i);
			jCheckBox.setText(iterator.next());
			jCheckBox.setVisible(true);
			i++;
		}

	}

	/**
	 * 环境面板加入参数和用户面板
	 */
	private void createEnvUserSetPanel(String env) {

		/*
		 * 上下两层网格布局
		 */
		JPanel envUserSetPanel = new JPanel(new GridLayout(2, 1));

		/*
		 * 加入环境参数设置面板
		 */
		MultiEnvArgumentsPanel argumentsPanel = new MultiEnvArgumentsPanel(env);
		envSetPaneMap.put(env, argumentsPanel);
		envUserSetPanel.add(argumentsPanel, BorderLayout.NORTH);

		/*
		 * 用户tab外层面板
		 */
		JPanel userPanel = new JPanel(new BorderLayout());
		userPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "设置当前环境用户")); // $NON-NLS-1$

		/*
		 * 用户tab面板
		 */
		JTabbedPane userTabPane = new JTabbedPane();

		userTabPane.addMouseListener(new MouseListener() {

			@Override
			public void mouseReleased(MouseEvent e) {
				// 返回此鼠标事件是否为该平台的弹出菜单触发事件。
				if (e.isPopupTrigger()) {

					// 只在选项卡上显示鼠标右键的提示
					// 在相对于初始组件的 x、y 位置上显示弹出式菜单。
					int i = userTabPane.indexAtLocation(e.getX(), e.getY());

					if (i != -1) {
						userTabPane.setSelectedIndex(i);

						JMenuItem rename = new JMenuItem("重命名");
						rename.addActionListener((e1) -> {
							JOptionPane.showMessageDialog(instance, "别急，还没实现！");
						});

						JMenuItem remove = new JMenuItem("移除");
						remove.addActionListener((e1) -> {
							/*
							 * 显示新的弹出框，用以确认移除环境
							 */
							removeUser(env, userTabPane.getTitleAt(i));
						});

						JPopupMenu pop = new JPopupMenu();
						pop.add(rename);
						pop.add(remove);

						pop.show(userTabPane, e.getX(), e.getY());
					}
				}

			}

			@Override
			public void mousePressed(MouseEvent e) {
			}

			@Override
			public void mouseExited(MouseEvent e) {
			}

			@Override
			public void mouseEntered(MouseEvent e) {
			}

			@Override
			public void mouseClicked(MouseEvent e) {
			}

		});

		userSetTabPaneMap.put(env, userTabPane);
		userPanel.add(userTabPane);

		envUserSetPanel.add(userPanel, BorderLayout.SOUTH);

		envSetPane.addTab(env, envUserSetPanel);

		userSetEnvArgumentsPanelMap.put(env, new HashMap<>());
	}

	private void initGui() {

		setLayout(new BorderLayout());
		setBorder(makeBorder());

		if (standalone) {
			add(makeTitlePanel(), BorderLayout.NORTH);
		}

		/*
		 * 中间面板
		 */
		JPanel mainPanel = new VerticalPanel();
		/*
		 * 加入环境选择
		 */
		if (standalone) {
			mainPanel.add(createEnvSelectPanel(), BorderLayout.NORTH);
		} else {
			add(createEnvSelectPanel(), BorderLayout.NORTH);

		}

		/*
		 * 加入环境和用户设置
		 */
		JPanel setPanel = new JPanel(new BorderLayout());
		setPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(), "设置环境和用户")); // $NON-NLS-1$

		envSetPane = new JTabbedPane();

		envSetPane.addMouseListener(new MouseListener() {

			@Override
			public void mouseReleased(MouseEvent e) {
				// 返回此鼠标事件是否为该平台的弹出菜单触发事件。
				if (e.isPopupTrigger()) {

					// 只在选项卡上显示鼠标右键的提示
					// 在相对于初始组件的 x、y 位置上显示弹出式菜单。
					int i = envSetPane.indexAtLocation(e.getX(), e.getY());
					if (i != -1) {
						envSetPane.setSelectedIndex(i);

						JMenuItem rename = new JMenuItem("重命名");
						rename.addActionListener((e1) -> {
							/*
							 * 显示新的弹出框，用以改名
							 */
							JOptionPane.showMessageDialog(instance, "还没实现！");
						});

						JMenuItem remove = new JMenuItem("移除");
						remove.addActionListener((e1) -> {
							/*
							 * 显示新的弹出框，用以确认移除环境
							 */
							removeEnv(envSetPane.getTitleAt(i));
						});

						JPopupMenu pop = new JPopupMenu();
						pop.add(rename);
						pop.add(remove);
						pop.show(envSetPane, e.getX(), e.getY());
					}
				}

			}

			@Override
			public void mousePressed(MouseEvent e) {
			}

			@Override
			public void mouseExited(MouseEvent e) {
			}

			@Override
			public void mouseEntered(MouseEvent e) {
			}

			@Override
			public void mouseClicked(MouseEvent e) {
			}

		});

		setPanel.add(envSetPane);

		mainPanel.add(setPanel, BorderLayout.CENTER);

		add(mainPanel, BorderLayout.CENTER);

		/*
		 * 环境选择面板 1.环境选择下拉框 2.用户选择下拉框 环境配置面板 3.添加新环境 tab选项卡面板 公共环境变量（全局非全局） 用户面板可添加多个用户
		 */

	}

	@Override
	public TestElement createTestElement() {
		MultiEnvUserController tg = new MultiEnvUserController();
		modifyTestElement(tg);
		return tg;
	}

	@Override
	public void modifyTestElement(TestElement tg) {
		super.configureTestElement(tg);
		if (tg instanceof MultiEnvUserController) {
			/*
			 * 保存选择的环境
			 */
			((MultiEnvUserController) tg).setSelectedEnv((String) envSelect.getSelectedItem());

			/*
			 * 保存选择的用户
			 */
			List<String> arrayList = new ArrayList<>();
			userSelectBoxList.stream().filter(o -> o.isSelected()).forEach(o -> {
				arrayList.add(o.getText());
			});

			((MultiEnvUserController) tg).setSelectedUser(arrayList);

			/*
			 * 保存环境的参数
			 */
			List<Arguments> envArgs = new ArrayList<Arguments>();
			envSetPaneMap.forEach((env, argsPanel) -> {
				Arguments args = (Arguments) argsPanel.createTestElement();
				args.setName("EnvUserArgs.env." + env);
				envArgs.add(args);
			});

			((MultiEnvUserController) tg).setEnvArgs(envArgs);

			/*
			 * 保存环境的用户的参数
			 */
			List<Arguments> userArgs = new ArrayList<Arguments>();
			userSetEnvArgumentsPanelMap.forEach((env, map) -> {
				map.forEach((user, userArgsPanel) -> {
					Arguments args = (Arguments) userArgsPanel.createTestElement();
					args.setName("EnvUserArgs.user." + env + "." + user);
					userArgs.add(args);
				});
			});

			((MultiEnvUserController) tg).setUserArgs(userArgs);

		}
	}

	@Override
	public void configure(TestElement tg) {
		super.configure(tg);
		if (tg instanceof MultiEnvUserController) {
			/*
			 * 先设置环境
			 */
			PropertyIterator envArgsIt = ((MultiEnvUserController) tg).getEnvArgs().iterator();

			while (envArgsIt.hasNext()) {
				JMeterProperty next = envArgsIt.next();

				Object args = next.getObjectValue();// Arguments EnvUserArgs.env.qa

				if (args instanceof Arguments) {
					String envName = ((Arguments) args).getName();// EnvUserArgs.env.qa

					String[] split = envName.split("\\.");// [EnvUserArgs,env,qa]
					if (split.length == 3 && ArgumentsType.env.name().equals(split[1])) {
						addNewEnv(split[2]);
						envSetPaneMap.get(split[2]).configure((Arguments) args);
					}

				}

			}

			/*
			 * 再设置用户
			 */
			PropertyIterator userArgsIt = ((MultiEnvUserController) tg).getUserArgs().iterator();// iterator里塞的各种参数

			while (userArgsIt.hasNext()) {
				JMeterProperty next = userArgsIt.next();

				Object args = next.getObjectValue();// Arguments EnvUserArgs.env.qa

				log.info(args.getClass().getSimpleName() + "=" + next.getName() + ":" + args);

				if (args instanceof Arguments) {
					String envName = ((Arguments) args).getName();// EnvUserArgs.env.qa.rd

					String[] split = envName.split("\\.");// [EnvUserArgs,env,qa,rd]
					if (split.length == 4 && ArgumentsType.user.name().equals(split[1])) {
						addNewUser(split[2], split[3]);
						userSetEnvArgumentsPanelMap.get(split[2]).get(split[3]).configure((Arguments) args);
					}

				}

			}

			/*
			 * 最后再选择环境
			 */
			envSelect.setSelectedItem(((MultiEnvUserController) tg).getSelectedEnv());

			/*
			 * 再选择用户
			 */
			((MultiEnvUserController) tg).getSelectedUser().forEach(user -> {
				userSelectBoxList.stream().forEach(box -> {
					if (box.getText().equals(user)) {
						box.setVisible(true);
						box.setSelected(true);
					}
				});
			});

		}

	}

	@Override
	public void clearGui() {
		super.clearGui();

		envSelect.removeAllItems();

		envSetPane.removeAll();

		envSetPaneMap.clear();
		userSetTabPaneMap.clear();
		userSetEnvArgumentsPanelMap.clear();
	}
}
